package com.lanyou.cook.web;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.lanyou.cook.common.Constants;
import com.lanyou.cook.datadictionary.InterfaceOperation;
import com.lanyou.cook.datadictionary.UserLogOpt;
import com.lanyou.cook.entity.domain.FieldSystem;
import com.lanyou.cook.entity.domain.InterfaceSchedule;
import com.lanyou.cook.entity.domain.KettleDataSourceEx;
import com.lanyou.cook.entity.domain.SystemInterface;
import com.lanyou.cook.entity.kettle.KettleDataSource;
import com.lanyou.cook.entity.kettle.KettleJob;
import com.lanyou.cook.entity.kettle.KettleJobEntryAttribute;
import com.lanyou.cook.repository.FieldSystemRepository;
import com.lanyou.cook.repository.InterfaceScheduleRepository;
import com.lanyou.cook.repository.KettleDataSourceExRepository;
import com.lanyou.cook.repository.KettleDataSourceRepository;
import com.lanyou.cook.repository.KettleJobEntryAttributeRepository;
import com.lanyou.cook.repository.KettleJobRepository;
import com.lanyou.cook.repository.SystemInterfaceRepository;
import com.lanyou.cook.service.InterfaceScheduleService;
import com.lanyou.cook.service.InterfaceVersionHistoryService;
import com.lanyou.cook.service.UserLogService;
import com.lanyou.cook.web.param.OnSaveJobParam;
import com.lanyou.cook.web.param.OnSaveTransformationParam;

/**
 * Kettle Spoon相关API控制层
 * 
 * @author 仇伟业
 *
 */
@RestController
@RequestMapping(Constants.BASE_URL_KETTLE_API )
public class KettleSpoonController {
	@Autowired
	private KettleDataSourceRepository kettleDataSourceRepository;
	@Autowired
	private KettleDataSourceExRepository kettleDataSourceExRepository;
	@Autowired
	private SystemInterfaceRepository systemInterfaceRepository;
	@Autowired
	private FieldSystemRepository fieldSystemRepository;   
	@Autowired
	private KettleJobRepository kettleJobRepository;
	@Autowired
	private InterfaceScheduleRepository interfaceScheduleRepository;
	@Autowired
	private InterfaceScheduleService interfaceScheduleService;
	@Autowired
	private InterfaceVersionHistoryService interfaceVersionHistoryService;
	@Autowired
	private UserLogService userLogService;
	@Autowired
	private KettleJobEntryAttributeRepository kettleJobEntryAttributeRepository;
	
	/**
	 * 获取默认的Kettle资源库元信息
	 * 
	 * @return 类型:String 如题
	 * @throws IOException
	 */
	@RequestMapping(value = "/defaultRepositoryMeta", produces = "application/json")
	public KettleDataSource getDefaultRepositoryMeta() throws IOException {
		return kettleDataSourceRepository
				.findByName(Constants.KETTLE_DEAFAULT_REPOSITORY_CONNECTION_NAME_IN_R_DATABASE);
	}

	/**
	 * 获取默认的Kettle作业日志设置
	 * 
	 * @return 类型:String 如题
	 * @throws IOException
	 */
	@RequestMapping(value = "/jobLogSetting", produces = "application/json")
	public String getJobLogSetting() {
		JsonObject result = new JsonObject();
		result.addProperty("ConnectionName",
				Constants.KETTLE_DEAFAULT_REPOSITORY_CONNECTION_NAME_IN_R_DATABASE);
		result.addProperty("JobLogTableName", Constants.KETTLE_JOB_LOG_TABLE_NAME);
		result.addProperty("JobChannelLogTableName", Constants.KETTLE_JOB_CHANNEL_LOG_TABLE_NAME);
		return result.toString();
	}

	@RequestMapping(value = "/checkSaveJob", method = RequestMethod.POST, produces = "application/json")
	public String checkSaveJob(@RequestBody OnSaveJobParam param) {
		JsonObject result = new JsonObject();
		String[] split = StringUtils.split(param.getJobPath(), '/');
		if (split.length != 2) {
			result.addProperty("valid", false);
			result.addProperty("msg", "请把接口保存在领域系统下");
			return result.toString();
		}

		String fieldName = split[0];
		String fieldSystemName = split[1];
		String operator = param.getOperator();
		if (Arrays.asList(fieldName, fieldSystemName, param.getJobName(), operator).stream().anyMatch(StringUtils::isBlank)) {
			result.addProperty("valid", false);
			result.addProperty("msg", "以下参数之一为空：领域、领域系统、作业名称、操作者");
			return result.toString();
		}

		FieldSystem ownerFieldSystem = fieldSystemRepository.findByNameAndField_Name(fieldSystemName, fieldName);
		if (ownerFieldSystem == null) {
			result.addProperty("valid", false);
			result.addProperty("msg", "无法找到对应的领域和领域系统");
			return result.toString();
		}

		if (!param.getIsNew()) {
			long kettleJobId = NumberUtils.toLong(param.getJobId());
			KettleJob kettleJob = kettleJobRepository.findOne(kettleJobId);
			if (kettleJob == null) {
				result.addProperty("valid", false);
				result.addProperty("msg", "无法找到对应的Kettle作业");
				return result.toString();
			}

			SystemInterface systemInterface = systemInterfaceRepository.findByKettleJob_Id(kettleJobId);
			if (systemInterface == null) {
				result.addProperty("valid", false);
				result.addProperty("msg", "无法找到关联的领域系统作业");
				return result.toString();
			}
		}

		result.addProperty("valid", true);
		return result.toString();
	}

	@RequestMapping(value = "/saveJob", method = RequestMethod.POST)
	@Transactional
	public void onSaveJob(@RequestBody OnSaveJobParam param) {
		String[] split = StringUtils.split(param.getJobPath(), '/');
		if (split.length != 2)
			return;

		String fieldName = split[0];
		String fieldSystemName = split[1];
		String operator = param.getOperator();
		if (Arrays.asList(fieldName, fieldSystemName, param.getJobName(), operator).stream().anyMatch(StringUtils::isBlank))
			return;

		FieldSystem ownerFieldSystem = fieldSystemRepository.findByNameAndField_Name(fieldSystemName, fieldName);
		if (ownerFieldSystem == null)
			return;

		long kettleJobId = NumberUtils.toLong(param.getJobId());
		KettleJob kettleJob = kettleJobRepository.findOne(kettleJobId);
		if (kettleJob == null)
			return;

		if (param.getIsNew()) {
			SystemInterface systemInterface = new SystemInterface();
			systemInterface.setJobName(param.getJobName());
			systemInterface.setOwnerFieldSystem(ownerFieldSystem);
			systemInterface.setKettleJob(kettleJob);
			List<Object[]> jobs = kettleJobRepository.findForMaxJobCodes();
		    ArrayList<Long> nums = new ArrayList<>();
		    if(jobs.size()>0){
			    for(Object[] job : jobs){
			    	String codeNums = job[2].toString();
			    	String bianma = codeNums.replace("ETL_发布方编码2接收方编码_", "");
			    	Long num = Long.parseLong(bianma);
			    	nums.add(num);
			    }
			    Collections.sort(nums);//排序
			    long codeNum = nums.get(nums.size()-1)+1;
			    DecimalFormat df1 = new DecimalFormat("000");
			    df1.format(codeNum);
			    systemInterface.setJobCode("ETL_发布方编码2接收方编码_"+df1.format(codeNum));
		    }else{
		    	systemInterface.setJobCode("ETL_发布方编码2接收方编码_001");
		    }

			systemInterfaceRepository.save(Arrays.asList(systemInterface));
			
			// 保存接口后保存历史版本
			interfaceVersionHistoryService.save(InterfaceOperation.新增, operator, true,
					systemInterface);
			// 记录用户日志
			String userLogContent = String.format("新增接口“%s”", param.getJobName());
			userLogService.save(UserLogOpt.MaintenanceInterface, operator, userLogContent);

		} else {
			SystemInterface systemInterface = systemInterfaceRepository.findByKettleJob_Id(kettleJobId);
			if (systemInterface == null)
				return;
			systemInterface.setJobName(param.getJobName());
			systemInterface.setOwnerFieldSystem(ownerFieldSystem);

			// 保存接口前保存历史版本
			interfaceVersionHistoryService.save(InterfaceOperation.修改, operator, true,
					systemInterface);
			
			systemInterfaceRepository.save(Arrays.asList(systemInterface));
	
			// 记录用户日志
			String userLogContent = String.format("修改接口“%s”", param.getJobName());
			userLogService.save(UserLogOpt.MaintenanceInterface, operator, userLogContent);
		}
	}

	@RequestMapping(value = "/checkDeleteJob", method = RequestMethod.POST, produces = "application/json")
	public String checkDeleteJob(@RequestBody OnSaveJobParam param) {
		JsonObject result = new JsonObject();
		String operator = param.getOperator();
		if(StringUtils.isEmpty(operator)){
			result.addProperty("valid", false);
			result.addProperty("msg", "操作者为空");
			return result.toString();
		}
		
		long kettleJobId = NumberUtils.toLong(param.getJobId());
		List<InterfaceSchedule> interfaceSchedules = interfaceScheduleRepository
				.findBySystemInterface_KettleJob_Id(kettleJobId);
		if (interfaceSchedules.isEmpty()) {
			result.addProperty("valid", true);
			return result.toString();
		}
		
		//在kettle工具里面删除作业时，需要对该作业是否存在调度进行判断，并提示用户先删调度再删作业（杨晨睿2017-03-09）
		/*if(interfaceSchedules != null && interfaceSchedules.size() > 0){
			result.addProperty("valid", false);
			result.addProperty("msg", "当前作业已存在调度，请到Cook接口管理平台先删除该接口对应的调度，然后再删除作业");
			return result.toString();
		}*/

		for(InterfaceSchedule interfaceSchedule : interfaceSchedules){
			if(!interfaceScheduleService.checkIsCanDelete(interfaceSchedule.getId())){
				result.addProperty("valid", false);
				result.addProperty("msg", "作业正在执行");
				return result.toString();
			}
		}
		
		result.addProperty("valid", true);
		return result.toString();
	}

	@RequestMapping(value = "/deleteJob", method = RequestMethod.POST)
	@Transactional
	public void onDeleteJob(@RequestBody OnSaveJobParam param) {
		String operator = param.getOperator();
		if(StringUtils.isEmpty(operator))
			return;
		
		long kettleJobId = NumberUtils.toLong(param.getJobId());
		SystemInterface systemInterface = systemInterfaceRepository.findByKettleJob_Id(kettleJobId);
		if (systemInterface == null)
			return;
		List<InterfaceSchedule> interfaceSchedules = interfaceScheduleRepository
				.findBySystemInterface_KettleJob_Id(kettleJobId);
		for(InterfaceSchedule interfaceSchedule : interfaceSchedules){
			if(!interfaceScheduleService.checkIsCanDelete(interfaceSchedule.getId()))
				return;
		}
		interfaceScheduleRepository.delete(interfaceSchedules);
		
		// 删除接口前保存历史版本
		
		interfaceVersionHistoryService.save(InterfaceOperation.删除,
				operator, true, systemInterface);
		
		systemInterfaceRepository.delete(Arrays.asList(systemInterface));
	
		// 记录用户日志
		String userLogContent = String.format("删除接口“%s”", systemInterface.getJobName());
		userLogService.save(UserLogOpt.MaintenanceInterface, operator,
				userLogContent);
	}
	
	@RequestMapping(value = "/checkSaveTrans", method = RequestMethod.POST, produces = "application/json")
	@Transactional
	public String checkSaveTrans(@RequestBody OnSaveTransformationParam param) {
		JsonObject result = new JsonObject();
		String[] split = StringUtils.split(param.getTransPath(), '/');
		if (split.length != 2) {
			result.addProperty("valid", false);
			result.addProperty("msg", "请把转换保存在领域系统下");
			return result.toString();
		}
		String fieldName = split[0];
		String fieldSystemName = split[1];
		String operator = param.getOperator();
		if (Arrays.asList(fieldName, fieldSystemName, operator).stream().anyMatch(StringUtils::isBlank)){
			result.addProperty("valid", false);
			result.addProperty("msg", "以下参数之一为空：领域、领域系统、转换名称、操作者");
			return result.toString();
		}
		
		FieldSystem ownerFieldSystem = fieldSystemRepository.findByNameAndField_Name(fieldSystemName, fieldName);
		if (ownerFieldSystem == null) {
			result.addProperty("valid", false);
			result.addProperty("msg", "无法找到对应的领域和领域系统");
			return result.toString();
		}
		
		result.addProperty("valid", true);
		return result.toString();
	}
	
	@RequestMapping(value = "/saveTrans", method = RequestMethod.POST)
	@Transactional
	public void onSaveTrans(@RequestBody OnSaveTransformationParam param) {
		if(param.isNew())
			return;
		String operator = param.getOperator();
		if(StringUtils.isEmpty(operator))
			return;
		
		// 按转换ID来保存的作业项属性
		List<KettleJobEntryAttribute> list1 = kettleJobEntryAttributeRepository.findByCodeAndValueStrAndJobEntry_Type_Code("trans_object_id", param.getTransId(), "TRANS");
//		// 按目录路径和转换名称来保存的作业项属性
//		List<KettleJobEntryAttribute> list2 = kettleJobEntryAttributeRepository.findByCodeAndValueStrAndJobEntry_Type_Code("dir_path", param.getTransPath(), "TRANS");
//		list2 = list2.stream().filter( attr -> {
//			long matchCount = kettleJobEntryAttributeRepository.countByCodeAndValueStrAndJobEntry_Id("name", newTransName, attr.getJobEntry().getId());
//			return (matchCount != 0);
//		}).collect(Collectors.toList());
		
		list1.stream().map(attr -> attr.getJob().getId()).distinct().forEach( kettleJobId ->{
			SystemInterface systemInterface = systemInterfaceRepository.findByKettleJob_Id(kettleJobId);
			if (systemInterface == null)
				return;
			// 保存接口前保存历史版本
			interfaceVersionHistoryService.save(InterfaceOperation.修改, operator, true,
					systemInterface);
			
			// 记录用户日志
			String userLogContent = String.format("修改接口“%s”", systemInterface.getJobName());
			userLogService.save(UserLogOpt.MaintenanceInterface, operator, userLogContent);
		});
	}
	
	@RequestMapping(value = "/checkDeleteTrans", method = RequestMethod.POST, produces = "application/json")
	@Transactional
	public String checkDeleteTrans(@RequestBody OnSaveTransformationParam param) {
		JsonObject result = new JsonObject();
		String operator = param.getOperator();
		if(StringUtils.isEmpty(operator)){
			result.addProperty("valid", false);
			result.addProperty("msg", "操作者为空");
			return result.toString();
		}
		
		result.addProperty("valid", true);
		return result.toString();
	}
	
	@RequestMapping(value = "/deleteTrans", method = RequestMethod.POST)
	@Transactional
	public void onDeleteTrans(@RequestBody OnSaveTransformationParam param) {
		String operator = param.getOperator();
		if(StringUtils.isEmpty(operator))
			return;
		// 按转换ID来保存的作业项属性
		List<KettleJobEntryAttribute> list1 = kettleJobEntryAttributeRepository.findByCodeAndValueStrAndJobEntry_Type_Code("trans_object_id", param.getTransId(), "TRANS");
		list1.stream().map(attr -> attr.getJob().getId()).distinct().forEach( kettleJobId ->{
			SystemInterface systemInterface = systemInterfaceRepository.findByKettleJob_Id(kettleJobId);
			if (systemInterface == null)
				return;
			// 保存接口前保存历史版本
			interfaceVersionHistoryService.save(InterfaceOperation.修改, operator, true,
					systemInterface);
			
			// 记录用户日志
			String userLogContent = String.format("修改接口“%s”", systemInterface.getJobName());
			userLogService.save(UserLogOpt.MaintenanceInterface, operator, userLogContent);
		});
	}
	
	@RequestMapping(value = "/{userCode}/dataSourceNames", method = RequestMethod.GET, produces = "application/json")
	public String getDataSourceNames(@PathVariable String userCode) {
		JsonArray results = new JsonArray();
		List<KettleDataSourceEx> dataSourceExs = kettleDataSourceExRepository.findByFieldSystem_Users_UserCode(userCode);
		for(KettleDataSourceEx dataSourceEx : dataSourceExs){
			results.add(new JsonPrimitive(dataSourceEx.getKettleDataSource().getName()));
		}
		
		return results.toString();
	}

}
